﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using mshtml;
using SHDocVw;

using System.Runtime.InteropServices;

namespace XDLogonMonitor {
    public class IEDDCControl {

        #region Variables
        [DllImport("user32.dll")]
        private static extern bool ShowWindow(IntPtr hwnd, int nCmdShow);
        private const int SW_MAXIMISE = 3;
        private object LOCK = "LOCK";
        private Boolean docComplete = false;
        private String currentURL = "";

        private object noValue = System.Reflection.Missing.Value;
        private SHDocVw.InternetExplorer shDocVwIE;
        private String _password = "";
        private String _username = "";
        private String _domain = "";

        public String username { set { _username = value; } }
        public String password { set { _password = value; } }
        public String domain { set { _domain = value; } }
        #endregion

        /// <summary>
        /// Initialize Internet Explorer including Event Handlers
        /// </summary>
        public IEDDCControl() {
            shDocVwIE = new InternetExplorer();
            shDocVwIE.DocumentComplete += new SHDocVw.DWebBrowserEvents2_DocumentCompleteEventHandler(OnDocumentComplete);
        }
        /// <summary>
        /// Quit IE, reset the shDocVwIE object and the event handler
        /// Don't know how much I like this...
        /// </summary>
        public void Reset() {
            shDocVwIE.Quit();

            shDocVwIE = new InternetExplorer();
            shDocVwIE.DocumentComplete += new SHDocVw.DWebBrowserEvents2_DocumentCompleteEventHandler(OnDocumentComplete);
        }
        /// <summary>
        /// Show IE Window, Navigate to URL of the DDC
        /// </summary>
        /// <param name="DDCUrl"></param>
        public void OpenIE(String DDCUrl) {
            try {
                ShowWindow((IntPtr)shDocVwIE.HWND, SW_MAXIMISE);
                shDocVwIE.Visible = true;
                shDocVwIE.Navigate(DDCUrl, ref noValue, ref noValue, ref noValue, ref noValue);
                WaitForPageLoad("aspx");
                Console.Error.WriteLine(DateTime.Now.Ticks.ToString());
            }
            catch (Exception e) {
                Console.Error.WriteLine(e.ToString());
            }
        }
        /// <summary>
        /// Processes the login to the web interface of the Desktop Delivery Controller
        /// </summary>
        public void ProcessLogin() {
            HTMLDocument document;
            HTMLInputElement loginButton;

            try {
                document = (HTMLDocument)shDocVwIE.Document;
                WaitForPageLoad("login.aspx");
                if (document.title.Contains("Logon")) {
                    InsertText("user", _username);
                    InsertText("password", _password);
                    InsertText("domain", _domain);
                    
                    loginButton = (HTMLInputElement)document.getElementById("login");
                    loginButton.click();
                }
                Console.Error.WriteLine(DateTime.Now.Ticks.ToString());
            }
            catch (Exception e) {
                Console.Error.WriteLine(e.ToString());
            }
        }
        /// <summary>
        /// Confirms page load.
        /// Locates A HREF, clicks link for requested desktop.
        /// </summary>
        public void ProcessDesktopLaunch(Boolean ignoreWait) {
            HTMLDocument document;
            try {
                document = (HTMLDocument)shDocVwIE.Document;
                if(!ignoreWait) WaitForPageLoad("default.aspx");
                if (document.title.Contains("Desktops")) {
                    FollowLink("Citrix.MPS.Desktop.Farm1.XenDesktop0020XP0020Shared");
                }
            }
            catch (Exception e) {
                Console.Error.WriteLine(e.ToString());
            }
        }
        /// <summary>
        /// Logout of the web interface
        /// </summary>
        public void ProcessLogout() {
            try {
                FollowLink("logoutAreaLogoutLink");
                shDocVwIE.Quit();
            }
            catch (Exception e) {
                Console.Error.WriteLine(e.ToString());
            }
        }
        /// <summary>
        /// Insert text into the field based on Element ID
        /// </summary>
        /// <param name="elementId"></param>
        /// <param name="value"></param>
        private void InsertText(String elementId, String value) {
            HTMLDocument document;
            HTMLInputElement inputElement;
            try {
                document = (HTMLDocument)shDocVwIE.Document;
                inputElement = (HTMLInputElement)document.getElementById(elementId);
                inputElement.value = value;
            }
            catch (Exception e) {
                Console.Error.WriteLine(e.ToString());
            }
        }
        /// <summary>
        /// Select A HREF and click the associated link
        /// </summary>
        /// <param name="elementId"></param>
        private void FollowLink(String elementId) {
            HTMLAnchorElement link;
            HTMLDocument document;
            try {
                document = (HTMLDocument)shDocVwIE.Document;
                link = (HTMLAnchorElement)document.getElementById(elementId);
                link.click();
            }
            catch(Exception e) {
                Console.Error.WriteLine(e.ToString());
            }
        }
        /// <summary>
        /// Monitors variable docComplete to change from false to true.  
        /// Confirms that URL contains variable urlContains.
        /// Changes variable docComplete back to false.
        /// </summary>
        /// <param name="urlContains"></param>
        private void WaitForPageLoad(String urlContains) {
            while (true) {
                if (docComplete && currentURL.Contains(urlContains))
                    break;
                System.Threading.Thread.Sleep(100);
                //what happens if I have been here a while?  Like 10 seconds and nothing happens?  Throw an Exception?
            }
            System.Threading.Monitor.Enter(LOCK);
            try {
                docComplete = false;
            }
            finally {
                System.Threading.Monitor.Exit(LOCK);
            }
        }
        /// <summary>
        /// Event handler, executes when IE Document load is complete.
        /// Changes variable docComplete to true
        /// Copies url to currentURL.
        /// </summary>
        /// <param name="disp"></param>
        /// <param name="url"></param>
        private void OnDocumentComplete(object disp, ref object url) {
            System.Threading.Monitor.Enter(LOCK);
            try {
                docComplete = true;
                currentURL = url.ToString();
            }
            finally {
                System.Threading.Monitor.Exit(LOCK);
            }
        }
    }
}
